using UnityEngine;
using System;
using System.Collections.Generic;

namespace Framework.UI
{
    public sealed class UIManager : FrameworkModule
    {
        public string UIRootPath { get; set; } = "UIRoot";

        private Resource.ResourceManager m_ResourceManager;
        private RectTransform m_UICanvas;
        private Camera m_UICamera;

        private Dictionary<Type, UIForm> m_Type2UIForm = new Dictionary<Type, UIForm>();
        private Dictionary<EUILayer, RectTransform> m_Layer2Parent = new Dictionary<EUILayer, RectTransform>();
        private Dictionary<EUILayer, int> m_Layer2Priority = new Dictionary<EUILayer, int>();
        private List<UIForm> m_FullSceenPanelList = new List<UIForm>();

        public override void Init()
        {
            this.m_ResourceManager = FrameworkEntry.GetModule<Resource.ResourceManager>();
            this.m_UICanvas = GameRoot.Instance.UICanvas;
            this.m_UICamera = GameRoot.Instance.UICamera;
            foreach (EUILayer layer in Enum.GetValues(typeof(EUILayer)))
            {
                RectTransform transLayer = new GameObject(layer.ToString(), typeof(RectTransform)).transform as RectTransform;
                transLayer.gameObject.layer = this.m_UICanvas.gameObject.layer;
                transLayer.SetParent(this.m_UICanvas);
                transLayer.ResetRPS();
                this.m_Layer2Parent[layer] = transLayer;
            }
        }

        public async FTask<UIForm> OpenUI(string assetUIPath)
        {
            GameObject result = await m_ResourceManager.LoadPrefabAsync(assetUIPath);
            GameObject goUI = GameObject.Instantiate(result, m_UICanvas);
            UIForm uiForm = goUI.GetComponent<UIForm>();
            this.m_Type2UIForm.Add(uiForm.GetType(), uiForm);
            RectTransform transParent = this.m_Layer2Parent[uiForm.Layer];
            goUI.transform.SetParent(transParent);
            goUI.transform.ResetRPS();
            if (uiForm.IsFullScreen)
            {
                int priority = this.GetPriorityByLayer(uiForm.Layer);
                int length = this.m_FullSceenPanelList.Count;
                int insertPos;
                for (insertPos = length; insertPos > 0; insertPos--)
                {
                    UIForm tempUIForm = this.m_FullSceenPanelList[insertPos - 1];
                    if (tempUIForm.FullScreenPriority < priority)
                    {
                        if (insertPos == length)
                        {
                            tempUIForm.gameObject.SetActive(false);
                        }
                        break;
                    }
                }
                this.m_FullSceenPanelList.Insert(insertPos, uiForm);
                uiForm.FullScreenPriority = priority;
            }
            return uiForm;
        }

        public void CloseUI(Type type)
        {
            UIForm uiForm;
            if (!this.m_Type2UIForm.TryGetValue(type, out uiForm))
            {
                return;
            }
            this.m_Type2UIForm.Remove(type);
            if (uiForm)
            {
                if (uiForm.IsFullScreen)
                {
                    this.m_Layer2Priority[uiForm.Layer]--;
                    this.m_FullSceenPanelList.Remove(uiForm);
                    int count = this.m_FullSceenPanelList.Count;
                    if (count > 0)
                    {
                        this.m_FullSceenPanelList[count - 1].gameObject.SetActive(true);
                    }
                }
                GameObject.Destroy(uiForm.gameObject);
            }
        }

        public void CloseUI(UIForm uiForm)
        {
            this.CloseUI(uiForm.GetType());
        }

        private int GetPriorityByLayer(EUILayer layer)
        {
            int priority;
            if (!this.m_Layer2Priority.TryGetValue(layer, out priority))
            {
                priority = 10 * (int)layer;
                this.m_Layer2Priority[layer] = priority + 1;
                return priority;
            }
            this.m_Layer2Priority[layer]++;
            return priority;
        }
        
    }
}